#ifndef _IM_SERVER_COMET_CONNECTION_
#define _IM_SERVER_COMET_CONNECTION_

#include <string>

#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>

// #include "http_parser.h"
// #include "mmap_file.h"

using namespace boost::asio;

namespace imserver {

class HttpRequest;
typedef boost::shared_ptr<HttpRequest> HttpRequestPtr;

class CometConnection;
typedef boost::shared_ptr<CometConnection> CometConnectionPtr;

class CometConnection : public boost::enable_shared_from_this<CometConnection> {
public:
  static CometConnectionPtr Create(boost::asio::io_service& io_service);
  ~CometConnection();

  static bool isHttpHeaderCompleted(const char * data, size_t len);
  static bool isHttpBodyCompleted(const std::string method,
      const std::map<std::string, std::string>& http_headers,
      const std::string& http_body);
  static bool parseKeyValue(const char * data, const char * key_seps,
      char kv_sep, std::map<std::string, std::string> * pairs);

  ip::tcp::socket& socket() {
    return socket_;
  }
  
  std::string remote_addr() const;

  bool isReadyForReceiveMsg() {
    return (valid_ && ready_);
  }

  void closeSocket() {
    valid_ = false;
    ready_ = false;
    socket_.close();
  }

  void Start();
  void AsyncRead();
  void AsyncWrite();
  void Abort();
  
  void WriteResponse(const std::string & response) {
    write_buf_ = response.c_str();
    write_buf_begin_ = 0;
    write_buf_end_ = response.size();
    AsyncWrite();
  }

  boost::asio::io_service & io_service() {
    return io_service_;
  }
private:
  CometConnection(boost::asio::io_service& io_service);
  /*HttpRequest * CreateRequest();*/
  void HandleRead(const boost::system::error_code& error, size_t bytes_transferred);
  void HandleWrite(const boost::system::error_code& /*error*/, size_t /*bytes_transferred*/);
  void onWriteComplete(const std::string& msg);
  bool buildHttpRequest(const std::string & data);
  void handleHttpRequest();

  boost::asio::io_service & io_service_;
  ip::tcp::socket socket_;

  /*HttpRequestPtr http_request_;*/
  std::map<std::string, std::string> http_headers_;
  std::map<std::string, std::string> http_cookies_;
  std::map<std::string, std::string> http_post_params_;
  std::string http_url_;
  std::string http_body_;
  int64_t uid_;

  bool ready_;
  bool valid_;

  enum { kReadBufLength = 4 * 1024 };

  char read_buf_[kReadBufLength];
  size_t read_buf_begin_, read_buf_end_;

  const char * write_buf_;
  size_t write_buf_begin_, write_buf_end_;
};

}

#endif // _IM_SERVER_COMET_CONNECTION_
